home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / fax2ps / fax2ps.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  18KB  |  692 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/fax/fax2ps/RCS/fax2ps.c,v 1.34 1994/03/16 00:09:31 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1991, 1992, 1993, 1994 by Sam Leffler.
  7.  * All rights reserved.
  8.  *
  9.  * This file is provided for unrestricted use provided that this
  10.  * legend is included on all tape media and as a part of the
  11.  * software program in whole or part.  Users may copy, modify or
  12.  * distribute this file at will.
  13.  */
  14. #include <math.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <time.h>
  19. #include <unistd.h>
  20.  
  21. #include "defs.h"
  22.  
  23. #define    MAXCODEPROBES    5
  24. CodeEntry* codehash[CODEHASH];
  25. CodeEntry* codetable;
  26.  
  27. char**    codeNames;        /* codeNames[code] => ASCII code name */
  28. char*    codeNameSpace;        /* storage space for codeNames and strings */
  29. int    ncodes = 0;        /* number of assigned codes */
  30. int    maxcodes = 0;        /* max # codes that fit in codetable */
  31. int    maxpairs = 0;        /* max # pairs that fit in pairtable */
  32. int    includeStatistics = FALSE;/* if 1, add comments w/ frequency stats */
  33. int    startOfRow;        /* if 1, have yet to emit a code for this row */
  34. int    dopairs = FALSE;    /* if 1, encode pairs of codes */
  35. float    defxres = 204.;        /* default x resolution (pixels/inch) */
  36. float    defyres = 98.;        /* default y resolution (lines/inch) */
  37. float    pageWidth = 8.5;    /* image page width (inches) */
  38. float    pageHeight = 11.0;    /* image page length (inches) */
  39. int    scaleToPage = FALSE;    /* if true, scale raster to page dimensions */
  40.  
  41. CodeEntry*
  42. enterCode(int dx, int len)
  43. {
  44.     int h, c;
  45.     CodeEntry* cp;
  46.  
  47.     cp = codehash[h = HASHCODE(dx,len)];
  48.     if (cp) {
  49.     if (cp->move == dx && cp->runlen == len)
  50.         return (cp);
  51.     c = h ? CODEHASH - h : 1;    /* Knott's rehash algorithm */
  52.     for (;;) {
  53.         if ((h -= c) < 0)
  54.         h += CODEHASH;
  55.         cp = codehash[h];
  56.         if (!cp)
  57.         break;
  58.         if (cp->move == dx && cp->runlen == len)
  59.         return (cp);
  60.     }
  61.     }
  62.     if (ncodes == maxcodes) {
  63.     maxcodes += MAXCODES;
  64.     codetable = (CodeEntry*) (maxcodes == MAXCODES ?
  65.         malloc(maxcodes * sizeof (CodeEntry)) :
  66.         realloc(codetable, maxcodes * sizeof (CodeEntry))
  67.     );
  68.     if (codetable == NULL) {
  69.         fprintf(stderr, "Panic, code table overflow\n");
  70.         exit(-1);
  71.     }
  72.     }
  73.     codehash[h] = cp = &codetable[ncodes++];
  74.     cp->c.count = 0;
  75.     cp->c.code = (u_short) -1;
  76.     cp->c.cost = 0;
  77.     cp->move = dx;
  78.     cp->runlen = len;
  79.     return (cp);
  80. }
  81.  
  82. void
  83. printCode(TIFF* tif, CodeEntry* cp)
  84. {
  85.     if (startOfRow) {
  86.     printf("%d r\n", fax.row);
  87.     startOfRow = FALSE;
  88.     }
  89.     if (cp->c.code == (u_short) -1)
  90.     printf("%d %d f", cp->runlen, cp->move);
  91.     else
  92.     printf("%s", codeNames[cp->c.code]);
  93.     putchar('\n');
  94. }
  95.  
  96. CodePairEntry* pairhash[PAIRHASH];
  97. CodePairEntry* pairtable;
  98. int    npairs = 0;
  99.  
  100. CodePairEntry*
  101. findPair(CodeEntry* a, CodeEntry* b)
  102. {
  103.     int h, c;
  104.     CodePairEntry* pp;
  105.  
  106.     pp = pairhash[h = HASHPAIR(a,b)];
  107.     if (pp->a == a && pp->b == b)
  108.     return (pp);
  109.     c = h ? PAIRHASH - h : 1;        /* Knott's rehash algorithm */
  110.     for (;;) {
  111.     if ((h -= c) < 0)
  112.         h += PAIRHASH;
  113.     pp = pairhash[h];
  114.     if (pp->a == a && pp->b == b)
  115.         return (pp);
  116.     }
  117.     /*NOTREACHED*/
  118. }
  119.  
  120. CodePairEntry*
  121. enterPair(CodeEntry* a, CodeEntry* b)
  122. {
  123.     int h, c;
  124.     CodePairEntry* pp;
  125.  
  126.     pp = pairhash[h = HASHPAIR(a,b)];
  127.     if (pp) {
  128.     if (pp->a == a && pp->b == b)
  129.         return (pp);
  130.     c = h ? PAIRHASH - h : 1;    /* Knott's rehash algorithm */
  131.     for (;;) {
  132.         if ((h -= c) < 0)
  133.         h += PAIRHASH;
  134.         pp = pairhash[h];
  135.         if (!pp)
  136.         break;
  137.         if (pp->a == a && pp->b == b)
  138.         return (pp);
  139.     }
  140.     }
  141.     if (npairs == maxpairs) {
  142.     maxpairs += MAXPAIRS;
  143.     pairtable = (CodePairEntry*) (maxpairs == MAXPAIRS ?
  144.         malloc(maxpairs * sizeof (CodePairEntry)) :
  145.         realloc(pairtable, maxpairs * sizeof (CodePairEntry))
  146.     );
  147.     if (pairtable == NULL) {
  148.         fprintf(stderr, "Panic, pair table overflow\n");
  149.         exit(-1);
  150.     }
  151.     }
  152.     pairhash[h] = pp = &pairtable[npairs++];
  153.     pp->c.count = 0;
  154.     pp->c.code = (u_short) -1;
  155.     pp->c.cost = 0;
  156.     pp->a = a;
  157.     pp->b = b;
  158.     return (pp);
  159. }
  160.  
  161. int
  162. printPair(TIFF* tif, CodeEntry* a, CodeEntry* b)
  163. {
  164.     CodePairEntry* pp = findPair(a,b);
  165.  
  166.     if (pp && pp->c.code != (u_short) -1) {
  167.     if (startOfRow) {
  168.         printf("%d r\n", fax.row);
  169.         startOfRow = FALSE;
  170.     }
  171.     printf("%s\n", codeNames[pp->c.code]);
  172.     return (TRUE);
  173.     } else
  174.     return (FALSE);
  175. }
  176.  
  177. #define    MIN(a,b)    ((a)<(b)?(a):(b))
  178.  
  179. static char alphabet[] = {
  180.     '!', '"', '#', '$', '&', '*', '+', ',', ':', ';', '?', '@',
  181.     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
  182.     'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  183.     '^', '_', '~'
  184. };
  185. static int MaxAlpha = (sizeof (alphabet) / sizeof (alphabet[0]));
  186.  
  187. /*
  188.  * Construct a table of code names from a limited
  189.  * alphabet.  By default, the alphabet is comprised
  190.  * of all the non-special ASCII PostScript characters
  191.  * (except for lower case alphabetics which are avoided
  192.  * to insure we don't construct a PostScript operator
  193.  * name).  The alphabet can be restricted to just the 
  194.  * upper case alphabetics with the -a option.
  195.  */
  196. void
  197. makeCodeNames(int ncodes)
  198. {
  199.     int n, cc, len, nc, digit, code;
  200.     char* cp;
  201.     short key[11];
  202.  
  203.     n = ncodes;
  204.     cc = 0;
  205.     len = 2;        /* minimum length string */
  206.     nc = 1;
  207.     do {
  208.     nc *= MaxAlpha;
  209.     cc += MIN(n, nc) * len++;
  210.     } while ((n -= MIN(n,nc)) > 0);
  211.     codeNameSpace = (char*) malloc(ncodes*sizeof (char*) + cc);
  212.     codeNames = (char**) codeNameSpace;
  213.     cp = (char*) (codeNames + ncodes);
  214.  
  215.     n = ncodes;
  216.     len = 1;
  217.     code = 0;
  218.     nc = 1;
  219.     for (digit = 0; digit < 11; digit++)
  220.     key[digit] = -1;
  221.     do {
  222.     nc *= MaxAlpha;
  223.     cc = MIN(n,nc);
  224.     while (cc-- > 0) {
  225.         for (digit = 0; ++key[digit] == MaxAlpha; key[digit++] = 0)
  226.         ;
  227.         codeNames[code++] = cp;
  228.         switch (len) {
  229.         case 5: *cp++ = alphabet[key[4]];
  230.         case 4: *cp++ = alphabet[key[3]];
  231.         case 3: *cp++ = alphabet[key[2]];
  232.         case 2: *cp++ = alphabet[key[1]];
  233.         case 1: *cp++ = alphabet[key[0]];
  234.         }
  235.         *cp++ = '\0';
  236.     }
  237.     len++;
  238.     } while ((n -= MIN(n,nc)) > 0);
  239. }
  240.  
  241. #define    DIGITS(x)    ((x) < 10 ? 1 : (x) < 100 ? 2 : (x) < 1000 ? 3 : 4)
  242.  
  243. int
  244. codeCost(CodeEntry* cp)
  245. {
  246.     /* 3 is constant overhead for <blank><len><blank><move>f */
  247.     return (3 + DIGITS(cp->move) + DIGITS(cp->runlen));
  248. }
  249.  
  250. /*
  251.  * DEFCOST is the cost to define the specified code for this
  252.  * move-draw operation.  It's calculated according to:
  253.  *    /<code>{<move-draw>}d\n
  254.  * which translates to 5 + cost(code) + cost(move-draw).
  255.  */
  256. #define    DEFCOST(mdc, codelen)    (mdc + codelen + 5)
  257. /*
  258.  * USECOST is the cost to use the code once it's been defined.
  259.  * This is just the number of uses times the length of the code
  260.  * plus one -- the one is for the blank needed by the parser.
  261.  */
  262. #define    USECOST(count, codelen)    (count * (codelen+1))
  263. /*
  264.  * CODEDCOST is the total cost to define and use the defined
  265.  * code (in place of straight move-draw operations).  We assume
  266.  * that the "code" field holds the result of the {pair|code}Cost
  267.  * calculation (see below).
  268.  */
  269. #define    CODEDCOST(c, codelen) \
  270.     (USECOST(c->count, codelen) + DEFCOST(c->code, codelen))
  271.  
  272. int
  273. codeLength(int code)
  274. {
  275.     return (code < MaxAlpha ? 1 : code < MaxAlpha*MaxAlpha ? 2 : 3);
  276. }
  277.  
  278. int
  279. codeCostCompare(const void* a1, const void* a2)
  280. {
  281.     const Code* c1 = *(const Code**)a1;
  282.     const Code* c2 = *(const Code**)a2;
  283.     return (c2->cost - c1->cost);
  284. }
  285.  
  286. /*
  287.  * Sort pairs and singletons, assign codes, and 
  288.  * reset counts for the next pass where we test
  289.  * out the encoding.
  290.  */
  291. int
  292. assignCodes(Code** sorted, int clearCounts)
  293. {
  294.     int i, n, code, codelen;
  295.     CodePairEntry* pp;
  296.     CodeEntry* cp;
  297.  
  298.     /*
  299.      * Calculate the cost to use the operation "as is"
  300.      * (i.e. w/o an encoding).  This is simply the number
  301.      * of uses times the cost of the move-draw operation.
  302.      * We save the {pair|code}Cost calculation for reuse
  303.      * below (when making the final decision about which
  304.      * codes are actually worth defining.
  305.      */
  306.     i = 0;
  307.     for (cp = codetable, n = ncodes; n-- > 0; i++, cp++) {
  308.     sorted[i] = &cp->c;
  309.     cp->c.code = codeCost(cp);
  310.     cp->c.cost = cp->c.count * cp->c.code;
  311.     }
  312.     for (pp = pairtable, n = npairs; n-- > 0; i++, pp++) {
  313.     sorted[i] = &pp->c;
  314.     pp->c.code = pp->a->c.code + pp->b->c.code;
  315.     pp->c.cost = pp->c.count * pp->c.code;
  316.     }
  317.     qsort(sorted, ncodes + npairs, sizeof (Code*), codeCostCompare);
  318.     code = 0;
  319.     codelen = codeLength(code);
  320.     for (i = 0, n = npairs + ncodes; n-- > 0; i++) {
  321.     Code* c = sorted[i];
  322.     if (c->cost > CODEDCOST(c, codelen)) {
  323.         c->code = code++;
  324.         codelen = codeLength(code);
  325.     } else
  326.         c->code = (u_short) -1;
  327.     if (clearCounts)
  328.         c->count = 0;
  329.     }
  330.     return (code);
  331. }
  332.  
  333. void
  334. makeCodeTable(void)
  335. {
  336.     int i, n;
  337.     Code** sorted;
  338.     CodeEntry* cp;
  339.  
  340.     sorted = (Code**) malloc((npairs+ncodes) * sizeof (Code*));
  341.     makeCodeNames(n = assignCodes(sorted, FALSE));
  342.     /*
  343.      * Oversize the dictionary in case the lookup function
  344.      * is optimized for a partially populated data structure.
  345.      * Most any hashing algorithm should do fine with a max
  346.      * 75% population.
  347.      */
  348.     printf("%d dict begin\n", 4*n/3);
  349.     for (i = 0, n = npairs + ncodes; n-- > 0; i++) {
  350.     Code* c = sorted[i];
  351.     if (c->code == (u_short) -1)
  352.         continue;
  353.     if (isPair(c)) {
  354.         CodePairEntry* pp = (CodePairEntry*) c;
  355.         printf("/%s{", codeNames[c->code]);
  356.         cp = pp->a;
  357.         if (cp->c.code < c->code)
  358.         printf("%s", codeNames[cp->c.code]);
  359.         else
  360.         printf("%d %d f", cp->runlen, cp->move);
  361.         putchar(' ');
  362.         cp = pp->b;
  363.         if (cp->c.code < c->code)
  364.         printf("%s", codeNames[cp->c.code]);
  365.         else
  366.         printf("%d %d f", cp->runlen, cp->move);
  367.         printf("}d");
  368.         if (includeStatistics)
  369.         printf("\t%% %d hits", c->count);
  370.         putchar('\n');
  371.     } else {
  372.         cp = (CodeEntry*) c;
  373.         printf("/%s{%d %d f}d", codeNames[c->code], cp->runlen, cp->move);
  374.         if (includeStatistics)
  375.         printf("\t%% %d hits", c->count);
  376.         putchar('\n');
  377.     }
  378.     }
  379.     free((char*) sorted);
  380. }
  381.  
  382. static void
  383. setupPass(TIFF* tif, int pass)
  384. {
  385.     long* stripbytecount;
  386.  
  387.     fax.pass = pass;
  388.     fax.row = 0;
  389.     TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbytecount);
  390.     fax.cc = stripbytecount[0];
  391.     fax.bp = fax.buf;
  392.     FaxPreDecode(tif);
  393. }
  394.  
  395. static    int totalPages = 0;
  396.  
  397. void
  398. printTIF(TIFF* tif, int pageNumber)
  399. {
  400.     u_long w, h;
  401.     short fill, unit, photometric, compression;
  402.     float xres, yres;
  403.     long g3opts;
  404.     long* stripbytecount;
  405.  
  406.     TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbytecount);
  407.     fax.cc = stripbytecount[0];
  408.     fax.buf = (u_char*) malloc(fax.cc);
  409.     TIFFReadRawStrip(tif, 0, fax.buf, fax.cc);
  410.     if (TIFFGetField(tif,TIFFTAG_FILLORDER, &fill) && fill != FILLORDER_MSB2LSB)
  411.     TIFFReverseBits(fax.buf, fax.cc);
  412.     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
  413.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
  414.     if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres)) {
  415.     TIFFWarning(TIFFFileName(tif),
  416.         "No x-resolution, assuming %g dpi", defxres);
  417.     xres = defxres;
  418.     }
  419.     if (!TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres)) {
  420.     TIFFWarning(TIFFFileName(tif),
  421.         "No y-resolution, assuming %g lpi", defyres);
  422.     yres = defyres;                    /* XXX */
  423.     }
  424.     if (TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &unit) &&
  425.       unit == RESUNIT_CENTIMETER) {
  426.     xres *= 25.4;
  427.     yres *= 25.4;
  428.     }
  429.     TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
  430.     fax.b.white = (photometric == PHOTOMETRIC_MINISBLACK);
  431.     /*
  432.      * Calculate the scanline/tile widths.
  433.      */
  434.     if (isTiled(tif)) {
  435.         fax.b.rowbytes = TIFFTileRowSize(tif);
  436.     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &fax.b.rowpixels);
  437.     } else {
  438.         fax.b.rowbytes = TIFFScanlineSize(tif);
  439.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &fax.b.rowpixels);
  440.     }
  441.     if (TIFFGetField(tif, TIFFTAG_GROUP3OPTIONS, &g3opts))
  442.     fax.is2d = (g3opts & GROUP3OPT_2DENCODING) != 0;
  443.     else
  444.     fax.is2d = 0;
  445.     fax.scanline = (u_char*) malloc(2*fax.b.rowbytes);
  446.     fax.b.refline = fax.scanline + fax.b.rowbytes;
  447.     TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
  448.     if (compression == COMPRESSION_CCITTFAX4)
  449.     fax.options = FAX3_NOEOL;
  450.     /*
  451.      * First pass: create code and pair frequency tables.
  452.      */
  453.     memset((char*) codehash, 0, sizeof (codehash));
  454.     memset((char*) pairhash, 0, sizeof (pairhash));
  455.     maxcodes = 0;
  456.     maxpairs = 0;
  457.     setupPass(tif, 1);
  458.     ncodes = npairs = 0;
  459.     if (compression == COMPRESSION_CCITTFAX4)
  460.     Fax4DecodeRow(tif, h*w);
  461.     else
  462.     Fax3DecodeRow(tif, h*w);
  463.     if (dopairs) {
  464.     /*
  465.      * Second pass: assign codes according to frequency
  466.      *  thresholds and rescan data to get true usage.
  467.      */
  468.     CodeEntry** sorted = (CodeEntry**)
  469.         malloc((npairs+ncodes) * sizeof (CodeEntry*));
  470.     assignCodes((Code**) sorted, TRUE);
  471.     free((char*) sorted);
  472.     setupPass(tif, 2);
  473.     if (compression == COMPRESSION_CCITTFAX4)
  474.         Fax4DecodeRow(tif, h*w);
  475.     else
  476.         Fax3DecodeRow(tif, h*w);
  477.     }
  478.     /*
  479.      * Third pass: generate code table and encoded data.
  480.      */
  481.     printf("%%%%Page: \"%d\" %d\n", pageNumber, pageNumber);
  482.     printf("gsave\n");
  483.     if (scaleToPage) {
  484.     float yscale = pageHeight / (h/yres);
  485.     float xscale = pageWidth / (w/xres);
  486.     printf("0 %d translate\n", (int)(yscale*(h/yres)*72.));
  487.     printf("%g %g scale\n", (72.*xscale)/xres, -(72.*yscale)/yres);
  488.     } else {
  489.     printf("0 %d translate\n", (int)(72.*h/yres));
  490.     printf("%g %g scale\n", 72./xres, -72./yres);
  491.     }
  492.     printf("0 setgray\n");
  493.     makeCodeTable();
  494.     setupPass(tif, 3);
  495.     while (fax.cc > 0) {
  496.     startOfRow = 1;
  497.     if (compression == COMPRESSION_CCITTFAX4)
  498.         Fax4DecodeRow(tif, w);
  499.     else
  500.         Fax3DecodeRow(tif, w);
  501.     if (!startOfRow)
  502.         printf("s\n");
  503.     }
  504.     printf("p\n");
  505.     printf("grestore\n");
  506.     free((char*) fax.scanline);
  507.     free((char*) fax.buf);
  508.     free(codeNameSpace);
  509.     if (maxcodes > 0) {
  510.     free((char*) codetable);
  511.     codetable = NULL;
  512.     }
  513.     if (maxpairs > 0) {
  514.     free((char*) pairtable);
  515.     pairtable = NULL;
  516.     }
  517.     totalPages++;
  518. }
  519.  
  520. #define    GetPageNumber(tif) \
  521. TIFFGetField(tif, TIFFTAG_PAGENUMBER, &pn, &ptotal)
  522.  
  523. int
  524. findPage(TIFF* tif, int pageNumber)
  525. {
  526.     short pn = -1, ptotal = -1;
  527.     if (GetPageNumber(tif)) {
  528.     while (pn != pageNumber && TIFFReadDirectory(tif) && GetPageNumber(tif))
  529.         ;
  530.     return (pn == pageNumber);
  531.     } else
  532.     return (TIFFSetDirectory(tif, pageNumber-1));
  533. }
  534.  
  535. void
  536. fax2ps(TIFF* tif, int npages, int* pages, char* filename)
  537. {
  538.     if (npages > 0) {
  539.     short pn, ptotal;
  540.     int i;
  541.  
  542.     if (!GetPageNumber(tif))
  543.         fprintf(stderr, "%s: No page numbers, counting directories.\n",
  544.         filename);
  545.     for (i = 0; i < npages; i++) {
  546.         if (findPage(tif, pages[i]))
  547.         printTIF(tif, pages[i]);
  548.         else
  549.         fprintf(stderr, "%s: No page number %d\n", filename, pages[i]);
  550.     }
  551.     } else {
  552.     int pageNumber = 1;
  553.     do
  554.         printTIF(tif, pageNumber++);
  555.     while (TIFFReadDirectory(tif));
  556.     }
  557. }
  558.  
  559. #undef GetPageNumber
  560.  
  561. static int
  562. pcompar(const void* va, const void* vb)
  563. {
  564.     const int* pa = (const int*) va;
  565.     const int* pb = (const int*) vb;
  566.     return (*pa - *pb);
  567. }
  568.  
  569. #ifndef atof            /* XXX for GNU gcc, gack! */
  570. extern    double atof();
  571. #endif
  572.  
  573. main(int argc, char** argv)
  574. {
  575.     extern int optind;
  576.     extern char* optarg;
  577.     int c, pageNumber;
  578.     int* pages = 0, npages = 0;
  579.     int dowarnings = FALSE;    /* if 1, enable library warnings */
  580.     long t;
  581.     TIFF* tif;
  582.  
  583.     while ((c = getopt(argc, argv, "p:x:y:W:H:aswzS")) != -1)
  584.     switch (c) {
  585.     case 'H':        /* page height */
  586.         pageHeight = atof(optarg);
  587.         break;
  588.     case 'S':        /* scale to page */
  589.         scaleToPage = TRUE;
  590.         break;
  591.     case 'W':        /* page width */
  592.         pageWidth = atof(optarg);
  593.         break;
  594.     case 'a':        /* use only upper-case alphabetics */
  595.         MaxAlpha = 26;
  596.         for (t = 0; t < MaxAlpha; t++)
  597.         alphabet[t] = 'A' + t;
  598.         break;
  599.     case 'p':        /* print specific page */
  600.         pageNumber = atoi(optarg);
  601.         if (pageNumber < 1) {
  602.         fprintf(stderr, "%s: Invalid page number (must be > 0).\n",
  603.             optarg);
  604.         exit(-1);
  605.         }
  606.         if (pages)
  607.         pages = (int*) realloc((char*) pages, (npages+1)*sizeof (int));
  608.         else
  609.         pages = (int*) malloc(sizeof (int));
  610.         pages[npages++] = pageNumber;
  611.         break;
  612.     case 's':        /* include frequency statistics as comments */
  613.         includeStatistics = TRUE;
  614.         break;
  615.     case 'w':
  616.         dowarnings = TRUE;
  617.         break;
  618.     case 'x':
  619.         defxres = atof(optarg);
  620.         break;
  621.     case 'y':
  622.         defyres = atof(optarg);
  623.         break;
  624.     case 'z':        /* do pair analysis (not effective) */
  625.         dopairs = TRUE;
  626.         break;
  627.     case '?':
  628.         fprintf(stderr,
  629. "usage: %s [-a] [-w] [-p pagenumber] [-x xres] [-y res] [-s] [-S] [-W pagewidth] [-H pageheight] [files]\n",
  630.         argv[0]);
  631.         exit(-1);
  632.     }
  633.     if (npages > 0)
  634.     qsort(pages, npages, sizeof (int), pcompar);
  635.     if (!dowarnings)
  636.     TIFFSetWarningHandler(0);
  637.     printf("%%!PS-Adobe-3.0\n");
  638.     printf("%%%%Creator: fax2ps\n");
  639. #ifdef notdef
  640.     printf("%%%%Title: %s\n", file);
  641. #endif
  642.     t = time(0);
  643.     printf("%%%%CreationDate: %s", ctime(&t));
  644.     printf("%%%%Origin: 0 0\n");
  645.     printf("%%%%BoundingBox: 0 0 %u %u\n",
  646.     (int)(pageHeight*72), (int)(pageWidth*72));    /* XXX */
  647.     printf("%%%%Pages: (atend)\n");
  648.     printf("%%%%EndComments\n");
  649.     printf("%%%%BeginProlog\n");
  650.     printf("/d{bind def}def\n");            /* bind and def proc */
  651.     printf("/f{0 rmoveto 0 rlineto}d\n");        /* fill span */
  652.     printf("/r{0 exch moveto}d\n");            /* begin row */
  653.     printf("/s{stroke}d\n");                /* stroke row */
  654.     printf("/p{end showpage}d \n");            /* end page */
  655.     printf("%%%%EndProlog\n");
  656.     if (optind < argc) {
  657.     do {
  658.         tif = TIFFOpen(argv[optind], "r");
  659.         if (tif) {
  660.         fax2ps(tif, npages, pages, argv[optind]);
  661.         TIFFClose(tif);
  662.         } else
  663.         fprintf(stderr, "%s: Can not open, or not a TIFF file.\n",
  664.             argv[optind]);
  665.     } while (++optind < argc);
  666.     } else {
  667.     int n, fd;
  668.     char temp[1024], buf[16*1024];
  669.  
  670.     strcpy(temp, "/tmp/fax2psXXXXXX");
  671.     fd = mkstemp(temp);
  672.     if (fd == -1) {
  673.         fprintf(stderr, "Could not create temp file \"%s\"\n", temp);
  674.         exit(-2);
  675.     }
  676.     while ((n = read(fileno(stdin), buf, sizeof (buf))) > 0)
  677.         write(fd, buf, n);
  678.     tif = TIFFOpen(temp, "r");
  679.     unlink(temp);
  680.     if (tif) {
  681.         fax2ps(tif, npages, pages, "<stdin>");
  682.         TIFFClose(tif);
  683.     } else
  684.         fprintf(stderr, "%s: Can not open, or not a TIFF file.\n", temp);
  685.     close(fd);
  686.     }
  687.     printf("%%%%Trailer\n");
  688.     printf("%%%%Pages: %u\n", totalPages);
  689.     printf("%%%%EOF\n");
  690.     exit(0);
  691. }
  692.